home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
By Popular Request 2.0
/
By Popular Request 2.0 (Arsenal Computer).ISO
/
amiga_6
/
tiffdtyp.lha
/
sources
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-08
|
26KB
|
876 lines
/*
* dispatch.c
*/
#include "classbase.h"
#include "TIFF.h"
#include "TIFFTags.h"
#include <libraries/xpksub.h>
#define DB(x) x;
#define DC(x) ;
#define DP(x) ;
#define SWAPW(a) (Rev ? (WORD)(((UWORD)a>>8)+((((UWORD)a&0xff)<<8))) : a)
#define SWAPU(a) (Rev ? (UWORD)(((UWORD)a>>8)+((((UWORD)a&0xff)<<8))) : a)
#define SWAPL(a) (Rev ? (LONG)(((ULONG)a>>24)+(((ULONG)a&0xff0000)>>8)+(((ULONG)a&0xff00)<<8)+(((ULONG)a&0xff)<<24)): a)
void ASM ReadShorts(REG (a0) BPTR fh, REG (a1) USHORT *buffer, REG (a2) TIFFTagItem *tag,REG (a6) struct ClassBase *cb);
void ASM ReadLongs(REG (a0) BPTR fh, REG (a1) ULONG *buffer, REG (a2) TIFFTagItem *tag,REG (a6) struct ClassBase *cb);
void ASM ReadRational(REG (a0) BPTR fh, REG (a1) struct Rational *buffer, REG (a2) TIFFTagItem *tag,REG (a6) struct ClassBase *cb);
void ASM ReadBytes(REG (a0) BPTR fh, REG (a1) UBYTE *buffer, REG (a2) TIFFTagItem *tag,REG (a6) struct ClassBase *cb);
int ASM UnPackLZW(REG (a0) UBYTE *source, REG (a1) UBYTE *dest, REG (d0) int len, REG (a6) struct ClassBase *cb);
void ASM InitializeStringTable(REG (a6) struct ClassBase *cb);
void ASM GetNextCode(REG (a6) struct ClassBase *cb);
void ASM AddStringToTable(REG (d0) int code,REG (d1) int newchar,REG (a6) struct ClassBase *cb);
void ASM WriteString(REG (d0) int code,REG (a6) struct ClassBase *cb);
void ASM IsInTable(REG (d0) int code,REG (a6) struct ClassBase *cb);
void ASM Chunky2Planar(REG (d0) int width,REG (a0) UBYTE *buffer,REG (a1) UBYTE *tempbmp);
#define TAGVAL(a,b) (SWAPW(a.Type)==TT_BYTE ? a.CValue[b] : \
(SWAPW(a.Type)==TT_SHORT ? SWAPW(a.SValue[b]) : \
(SWAPW(a.Type)==TT_LONG ? SWAPL(a.LValue) : \
~0)))
char Rev=0; /* flag for reverse byte order */
void *pool,*poolchip; /* memory pool for allocations */
struct BitMapHeader *bmhd;
struct StringEntry
{
struct StringEntry *OldCode;
UWORD StringLen;
UBYTE FirstChar;
UBYTE LastChar;
} *StringTable;
TIFFBasicFields BF={
2, /* GrayResponseUnit */
0, /* NewSubfileType */
0, /* PhotometricInterpretation */
CHUNKY, /* PlanarConfiguration */
NO_PREDICTOR, /* Predictor */
INCH, /* ResolutionUnit */
1, /* SamplesPerPixel */
NO_COMPRESSION, /* Compression */
{1}, /* BitsPerSample */
NULL, /* ColorMap */
NULL, /* ColorResponseCurve */
NULL, /* GrayResponseCurve */
0, /* ImageLength */
0, /* ImageWidth */
(USHORT)~0, /* RowsPerStrip */
NULL, /* StripByteCounts */
NULL, /* StripOffsets */
};
TIFFInformationFields IF={NULL,NULL,NULL,NULL,NULL,NULL,};
TIFFFaxFields FF={0,0};
TIFFDocumentFields DF={
NULL, /* DocumentName */
NULL, /* PageName */
LINE_ART, /* Threshhold */
TOPLEFT, /* Orientation */
0, /* CellLength */
0, /* CellWidth */
MSB_FIRST, /* FillOrder */
0,0, /* PageNumber */
{0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff,0xffff,0xffff}, /* MaxSampleValue */
{0,0,0,0,0,0,0,0}, /* MinSampleValue */
};
/*****************************************************************************/
struct RGBQuad
{
UBYTE rgbBlue;
UBYTE rgbGreen;
UBYTE rgbRed;
UBYTE rgbReserved;
};
#define QSIZE (sizeof (struct RGBQuad))
/*****************************************************************************/
BOOL ASM GetTIFF (REG (a6) struct ClassBase *cb, REG (a0) Class * cl, REG (a2) Object * o, REG (a1) struct TagItem * attrs);
BOOL ASM convert(REG (a6) struct ClassBase *cb,REG (a0) BPTR fh, REG (a1) Object * o);
ULONG setdtattrs (struct ClassBase *cb, Object * o, ULONG data,...)
{
return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
}
/*****************************************************************************/
ULONG getdtattrs (struct ClassBase *cb, Object * o, ULONG data,...)
{
return (GetDTAttrsA (o, (struct TagItem *) & data));
}
/*****************************************************************************/
Class *initClass (struct ClassBase *cb)
{
Class *cl;
if (cl = MakeClass (TIFFDTCLASS, PICTUREDTCLASS, NULL, NULL, 0L))
{
cl->cl_Dispatcher.h_Entry = Dispatch;
cl->cl_UserData = (ULONG) cb;
AddClass (cl);
}
return (cl);
}
/*****************************************************************************/
ULONG ASM Dispatch (REG (a0) Class * cl, REG (a2) Object * o, REG (a1) Msg msg)
{
struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
ULONG retval;
switch (msg->MethodID)
{
case OM_NEW:
if (retval = DoSuperMethodA (cl, o, msg))
{
DB (KPrintF ("OM_NEW\n"));
if (!GetTIFF (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList))
{
CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
return NULL;
}
}
break;
/* Let the superclass handle everything else */
default:
retval = (ULONG) DoSuperMethodA (cl, o, msg);
break;
}
return (retval);
}
BOOL ASM GetTIFF (REG (a6) struct ClassBase *cb, REG (a0) Class * cl, REG (a2) Object * o, REG (a1) struct TagItem * attrs)
{
TIFFImageFileHeader ifh;
TIFFTagItem tti;
short NumTags;
LONG i;
STRPTR title;
BPTR fh;
BOOL flag=FALSE;
title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
setdtattrs (cb, o,DTA_ObjName,title,TAG_DONE);
DB (KPrintF ("GetTIFF %s\n",title));
pool=CreatePool(MEMF_CLEAR,8192,8192);
if(!pool) return FALSE;
if ((getdtattrs (cb, o, DTA_Handle, &fh, PDTA_BitMapHeader, &bmhd, TAG_DONE) == 2) && fh)
{
DB (KPrintF ("GetDTAttrs\n"));
Seek (fh, 0L, OFFSET_BEGINNING);
/* read image file header */
if (Read (fh, &ifh, TIFHSIZE) == TIFHSIZE)
{
if (ifh.ByteOrder == 'II')
{
DB (KPrintF ("reverse byte order\n"));
Rev=1;
}
else if (ifh.ByteOrder == 'MM')
{
DB (KPrintF ("normal byte order\n"));
Rev=0;
}
else
SetIoErr (ERROR_OBJECT_WRONG_TYPE);
DB (KPrintF ("Version %lx %lx\n",(long)ifh.Version,(long)SWAPW(ifh.Version)));
DB (KPrintF ("Offset %lx %lx\n",ifh.Offset,SWAPL(ifh.Offset)));
}
else
{
DB (KPrintF ("couldn't read information\n"));
DeletePool(pool);
return FALSE;
}
Seek (fh, SWAPL(ifh.Offset), OFFSET_BEGINNING);
/* read image file directory */
if (Read (fh, &NumTags, sizeof(short)) == sizeof(short))
{
NumTags=SWAPW(NumTags);
for(i=0;i<NumTags;i++)
{
if (Read (fh, &tti, TTISIZE) == TTISIZE)
{
DB ( KPrintF("%ld:\n",(long)SWAPW(tti.Tag)));
tti.Count=SWAPL (tti.Count);
switch (SWAPW (tti.Tag))
{
case TT_NewSubfileType:
BF.NewSubfileType=TAGVAL(tti,0);
DB ( KPrintF("tag NewSubfileType\n"));
break;
case TT_SubfileType:
switch(TAGVAL(tti,0))
{
case REDUCED_RESOLUTION:
BF.NewSubfileType|=REDUCED;
break;
case MULTI_PAGE:
BF.NewSubfileType|=MULTIPAGE;
break;
}
DB ( KPrintF("tag SubfileType\n"));
break;
case TT_ImageWidth:
bmhd->bmh_Width=BF.ImageWidth=TAGVAL(tti,0);
DB ( KPrintF("ImageWidth %ld\n",BF.ImageWidth));
break;
case TT_ImageLength:
bmhd->bmh_Height=BF.ImageLength=TAGVAL(tti,0);
DB ( KPrintF("ImageLength %ld\n",BF.ImageLength));
if(BF.RowsPerStrip==(USHORT)~0)
BF.RowsPerStrip=BF.ImageLength;
break;
case TT_BitsPerSample:
if(tti.Count>2)
ReadShorts(fh,BF.BitsPerSample,&tti,cb);
else
BF.BitsPerSample[0]=TAGVAL(tti,0);
if(tti.Count==2)
BF.BitsPerSample[1]=TAGVAL(tti,1);
if(DF.MaxSampleValue[0]==~0)
{
int i;
for(i=0;i<8;i++)
DF.MaxSampleValue[i]=(2<<BF.BitsPerSample[i])-1;
}
DB ( KPrintF("BitPerSample %ld %lx\n",(long)BF.BitsPerSample[0],(long)tti.LValue));
break;
case TT_Compression:
BF.Compression=TAGVAL(tti,0);
DB ( KPrintF("Compression %ld\n",(long)BF.Compression));
break;
case TT_PhotometricInterpretation:
BF.PhotometricInterpretation=TAGVAL(tti,0);
DB ( KPrintF("PhotometricInterpretation %ld\n",(long)BF.PhotometricInterpretation));
break;
case TT_Threshholding:
DF.Threshholding=TAGVAL(tti,0);
DB ( KPrintF("Threshholding %ld\n",(long)DF.Threshholding));
break;
case TT_CellWidth:
DF.CellWidth=TAGVAL(tti,0);
DB ( KPrintF("CellWidth %ld\n",(long)DF.CellWidth));
break;
case TT_CellLength:
DF.CellLength=TAGVAL(tti,0);
DB ( KPrintF("CellLength %ld\n",(long)DF.CellLength));
break;
case TT_FillOrder:
DF.FillOrder=TAGVAL(tti,0);
DB ( KPrintF("FillOrder %ld\n",(long)DF.FillOrder));
break;
case TT_DocumentName:
DF.DocumentName=AllocPooled(pool,tti.Count);
if(!DF.DocumentName) goto abort;
ReadBytes(fh,DF.DocumentName,&tti,cb);
DB ( KPrintF("DocumentName %s\n",DF.DocumentName));
break;
case TT_ImageDescription:
IF.ImageDescription=AllocPooled(pool,tti.Count);
if(!IF.ImageDescription) goto abort;
ReadBytes(fh,IF.ImageDescription,&tti,cb);
DB ( KPrintF("ImageDescription %s\n",IF.ImageDescription));
break;
case TT_Make:
IF.Make=AllocPooled(pool,tti.Count);
if(!IF.Make) goto abort;
ReadBytes(fh,IF.Make,&tti,cb);
DB ( KPrintF("Make %s\n",IF.Make));
break;
case TT_Model:
IF.Model=AllocPooled(pool,tti.Count);
if(!IF.Model) goto abort;
ReadBytes(fh,IF.Model,&tti,cb);
DB ( KPrintF("Model %s\n",IF.Model));
break;
case TT_StripOffsets:
BF.StripOffsets=AllocPooled(pool,tti.Count*sizeof(long));
DB ( KPrintF("StripOffsets %ld\n",(long)tti.Count));
if(!BF.StripOffsets) goto abort;
ReadLongs(fh,BF.StripOffsets,&tti,cb);
break;
case TT_Orientation:
DF.Orientation=TAGVAL(tti,0);
DB ( KPrintF("Orientation %ld\n",(long)DF.Orientation));
break;
case TT_SamplesPerPixel:
BF.SamplesPerPixel=TAGVAL(tti,0);
DB ( KPrintF("SamplePerPixel %ld\n",(long)BF.SamplesPerPixel));
break;
case TT_RowsPerStrip:
BF.RowsPerStrip=TAGVAL(tti,0);
DB ( KPrintF("RowsPerStrip %ld\n",(long)BF.RowsPerStrip));
break;
case TT_StripByteCounts:
BF.StripByteCounts=AllocPooled(pool,tti.Count*sizeof(long));
DB ( KPrintF("StripByteCounts %ld\n",(long)tti.Count));
if(!BF.StripByteCounts) goto abort;
ReadLongs(fh,BF.StripByteCounts,&tti,cb);
break;
case TT_MaxSampleValue:
DB ( KPrintF("MaxSampleValue %ld\n",(long)tti.Count));
ReadShorts(fh,DF.MaxSampleValue,&tti,cb);
break;
case TT_MinSampleValue:
DB ( KPrintF("MinSampleValue %ld\n",(long)tti.Count));
ReadShorts(fh,DF.MinSampleValue,&tti,cb);
break;
case TT_XResolution:
ReadRational(fh,&BF.XResolution,&tti,cb);
DB ( KPrintF("XResolution %ld / %ld\n",(long)BF.XResolution.Numerator,BF.XResolution.Denominator));
break;
case TT_YResolution:
ReadRational(fh,&BF.YResolution,&tti,cb);
DB ( KPrintF("YResolution %ld / %ld\n",(long)BF.YResolution.Numerator,BF.YResolution.Denominator));
break;
case TT_PlanarConfiguration:
BF.PlanarConfiguration=TAGVAL(tti,0);
DB ( KPrintF("PlanarConfiguration %ld\n",(long)BF.PlanarConfiguration));
break;
case TT_PageName:
DF.PageName=AllocPooled(pool,tti.Count);
if(!DF.PageName) goto abort;
ReadBytes(fh,DF.PageName,&tti,cb);
DB ( KPrintF("PageName %s\n",DF.PageName));
break;
case TT_XPosition:
ReadRational(fh,&DF.XPosition,&tti,cb);
DB ( KPrintF("XPosition %ld / %ld\n",(long)DF.XPosition.Numerator,DF.XPosition.Denominator));
break;
case TT_YPosition:
ReadRational(fh,&DF.XPosition,&tti,cb);
DB ( KPrintF("YPosition %ld / %ld\n",(long)DF.YPosition.Numerator,DF.YPosition.Denominator));
break;
case TT_GrayResponseUnit:
BF.GrayResponseUnit=TAGVAL(tti,0);
DB ( KPrintF("GrayResponseUnit %d\n",(int)BF.GrayResponseUnit));
break;
case TT_GrayResponseCurve:
BF.GrayResponseCurve=AllocPooled(pool,tti.Count*sizeof(short));
DB ( KPrintF("GrayResponseCurve size %ld\n",(long)tti.Count));
if(!BF.GrayResponseCurve) goto abort;
ReadShorts(fh,BF.GrayResponseCurve,&tti,cb);
break;
case TT_Group3Options:
FF.Group3Options=TAGVAL(tti,0);
DB ( KPrintF("Group3Options %x\n",(int)FF.Group3Options));
break;
case TT_Group4Options:
FF.Group4Options=TAGVAL(tti,0);
DB ( KPrintF("Group4Options %x\n",(int)FF.Group4Options));
break;
case TT_ResolutionUnit:
BF.ResolutionUnit=TAGVAL(tti,0);
DB ( KPrintF("ResolutionUnit %ld\n",(long)BF.ResolutionUnit));
break;
case TT_PageNumber:
DB ( KPrintF("PageNumber\n"));
ReadShorts(fh,DF.PageNumber,&tti,cb);
DB ( KPrintF(" %d %d\n",(int)DF.PageNumber[0],(int)DF.PageNumber[1]));
break;
case TT_ColorResponseCurves:
BF.ColorResponseCurves=AllocPooled(pool,tti.Count*sizeof(short));
DB ( KPrintF("ColorResponseCurves size %ld\n",(long)tti.Count));
if(!BF.ColorResponseCurves) goto abort;
ReadShorts(fh,BF.ColorResponseCurves,&tti,cb);
break;
case TT_Software:
IF.Software=AllocPooled(pool,tti.Count);
DB ( KPrintF("Software %s\n",IF.Software));
if(!IF.Software) goto abort;
ReadBytes(fh,IF.Software,&tti,cb);
break;
case TT_DateTime:
DB ( KPrintF("DateTime %s\n",IF.DateTime));
ReadBytes(fh,IF.DateTime,&tti,cb);
break;
case TT_Artist:
IF.Artist=AllocPooled(pool,tti.Count);
DB ( KPrintF("Artist %s\n",IF.Artist));
if(!IF.Artist) goto abort;
ReadBytes(fh,IF.Artist,&tti,cb);
break;
case TT_HostComputer:
IF.HostComputer=AllocPooled(pool,tti.Count);
DB ( KPrintF("HostComputer %s\n",IF.HostComputer));
if(!IF.HostComputer) goto abort;
ReadBytes(fh,IF.HostComputer,&tti,cb);
break;
case TT_Predictor:
BF.Predictor=TAGVAL(tti,0);
DB ( KPrintF("Predictor %ld\n",(long)BF.Predictor));
break;
case TT_WhitePoint:
DB ( KPrintF("tag WhitePoint\n"));
break;
case TT_PrimaryChromaticities:
DB ( KPrintF("tag PrimaryChromaticities\n"));
break;
case TT_ColorMap:
BF.ColorMap=AllocPooled(pool,tti.Count*sizeof(short));
DB ( KPrintF("ColorMap size %ld\n",(long)tti.Count));
if(!BF.ColorMap) goto abort;
ReadShorts(fh,BF.ColorMap,&tti,cb);
break;
case TT_InkSet:
DB ( KPrintF("tag InkSet\n"));
break;
case TT_InkNames:
DB ( KPrintF("tag InkNames\n"));
break;
case TT_TargetPrinter:
DB ( KPrintF("tag TargetPrinter\n"));
break;
case TT_JPEGProc:
DB ( KPrintF("tag JPEGProc\n"));
break;
case TT_JPEGInterchangeFormat:
DB ( KPrintF("tag JPEGInterchangeFormat:\n"));
break;
case TT_JPEGInterchangeFormatLength:
DB ( KPrintF("tag JPEGInterchangeFormatLength\n"));
break;
case TT_JPEGLosslessPredictors:
DB ( KPrintF("tag JPEGLosslessPredictors\n"));
break;
case TT_JPEGQTables:
DB ( KPrintF("tag JPEGQTables\n"));
break;
case TT_JPEGDCTables:
DB ( KPrintF("tag JPEGDCTables\n"));
break;
case TT_JPEGACTables:
DB ( KPrintF("tag JPEGACTables\n"));
break;
case TT_YCbCrCoefficents:
DB ( KPrintF("tag YCbCrCoefficents\n"));
break;
case TT_YCbCrSubSampling:
DB ( KPrintF("tag YCbCrSubSampling\n"));
break;
case TT_YCbCrPositioning:
DB ( KPrintF("tag YCbCrPositioning\n"));
break;
default:
DB (KPrintF ("Unknown tag %ld\n", (long)SWAPW (tti.Tag)));
break;
}
}
else
{
DB (KPrintF ("couldn't read information\n"));
DeletePool(pool);
return FALSE;
}
}
}
}
flag=convert(cb,fh,o);
abort:
DeletePool(pool);
return flag;
}
/* converts the image in BitMap format */
BOOL ASM convert(REG (a6) struct ClassBase *cb,REG (a0) BPTR fh, REG (a1) Object * o)
{
ULONG modeid = HIRES_KEY;
struct RastPort rp;
LONG i, j, k, l, m;
struct BitMap *bm=NULL,tbm;
UBYTE *buffer,*buffer3,*ErrRed,*ErrGreen,*ErrBlue;
LONG depth,ncolors;
struct ColorRegister *cmap;
LONG *cregs;
DB (KPrintF ("Convert:\n"));
DB ( KPrintF("BitPerSample %ld \n",(long)BF.BitsPerSample[0]));
depth=BF.BitsPerSample[0];
DB ( KPrintF("depth %ld \n",(long)depth));
ncolors=1<<depth;
DB (KPrintF ("NColors %ld\n",ncolors));
setdtattrs (cb, o, PDTA_NumColors, ncolors, TAG_DONE);
getdtattrs (cb, o,
PDTA_ColorRegisters, (ULONG)&cmap,
PDTA_CRegs, &cregs,
TAG_DONE);
switch(BF.Compression)
{
case NO_COMPRESSION:
break;
case LZW:
/* allocate LZW table */
StringTable=AllocPooled(pool,sizeof(struct StringEntry)*4096);
if(StringTable==NULL)
{
DB (KPrintF ("Unable to allocate LZW string table\n"));
goto abort;
}
/* initialize first entries for lzw decompression table */
for(i=0;i<256;i++)
{
StringTable[i].StringLen=1;
StringTable[i].FirstChar=StringTable[i].LastChar=i;
}
break;
default:
DB (KPrintF ("Unsupported Compression\n"));
goto abort;
}
switch(BF.PhotometricInterpretation)
{
case BILEVEL_ZERO_IS_WHITE:
for(i=0;i<ncolors;i++)
{
/* Set the master color table */
cmap->red = cmap->green = cmap->blue = (0xff/((1<<BF.BitsPerSample[0])-1))*(ncolors-i-1);
/* Set the color table used for remapping */
cregs[i*3+0] = cregs[i*3+1] = cregs[i*3+2] = cmap->blue<<24;
cmap++;
}
break;
case BILEVEL_ZERO_IS_BLACK:
for(i=0;i<ncolors;i++)
{
/* Set the master color table */
cmap->red = cmap->green = cmap->blue = (0xff/((1<<BF.BitsPerSample[0])-1))*i;
/* Set the color table used for remapping */
cregs[i*3+0] = cregs[i*3+1] = cregs[i*3+2] = cmap->blue<<24;
cmap++;
}
break;
case TRUE_COLOR_RGB:
for(i=0;i<ncolors;i++)
{
/* Set the master color table */
cmap->red = i & 0xe0;
cmap->green = (i<<3) & 0xe0;
cmap->blue = i<<6;
/* Set the color table used for remapping */
cregs[i*3+0] = cmap->red << 24;
cregs[i*3+1] = cmap->green << 24;
cregs[i*3+2] = cmap->blue << 24;
cmap++;
}
/* allocate buffer for Floyd-Steinberg dithering */
ErrRed=AllocPooled(pool,BF.ImageWidth+1);
ErrGreen=AllocPooled(pool,BF.ImageWidth+1);
ErrBlue=AllocPooled(pool,BF.ImageWidth+1);
break;
case COLOR_MAPPED_RGB:
DB (KPrintF ("Color Mapped depth=%ld\n",depth));
for(i=0;i<ncolors;i++)
{
/* Set the master color table */
cmap->red = BF.ColorMap[i+0*ncolors];
cmap->green = BF.ColorMap[i+1*ncolors];
cmap->blue = BF.ColorMap[i+2*ncolors];
cmap++;
/* Set the color table used for remapping */
cregs[i*3+0] = BF.ColorMap[i+0*ncolors] << 16;
cregs[i*3+1] = BF.ColorMap[i+1*ncolors] << 16;
cregs[i*3+2] = BF.ColorMap[i+2*ncolors] << 16;
}
break;
default:
DB (KPrintF ("Unsupported Photometric Interpretation\n"));
return FALSE;
}
DB (KPrintF ("getattrs\n"));
bmhd->bmh_Depth=depth;
/* Initialize the temporary bitmap */
poolchip=CreatePool(MEMF_CLEAR|MEMF_CHIP,8192,8192);
if(!poolchip) return FALSE;
InitBitMap(&tbm, 8, (BF.ImageWidth +31)&~0x1f, BF.RowsPerStrip);
if(!(tbm.Planes[0]=AllocPooled(poolchip,tbm.BytesPerRow*tbm.Rows*8)))
{
DB (KPrintF ("Unable to allocate temporary bitmap\n"));
goto abort;
}
for(i=1;i<8;i++)
tbm.Planes[i]=tbm.Planes[i-1]+tbm.BytesPerRow*tbm.Rows;
/* allocate bitmap */
if (bm = AllocBitMap (BF.ImageWidth, BF.ImageLength, depth, BMF_CLEAR, NULL))
{
InitRastPort (&rp);
rp.BitMap = bm;
DB (KPrintF ("Allocated bitmap\n"));
}
else
{
DB (KPrintF ("Unable to allocate bitmap\n"));
goto abort;
}
buffer=AllocPooled(pool,BF.RowsPerStrip*tbm.BytesPerRow*8*BF.SamplesPerPixel);
if(!buffer)
{
DB (KPrintF ("Unable to allocate buffer %ld\n",BF.RowsPerStrip*tbm.BytesPerRow*8*BF.SamplesPerPixel));
goto abort;
}
DB (KPrintF ("Allocated buffer\n"));
m=0;
for(i=0;i<(BF.ImageLength + BF.RowsPerStrip - 1) / BF.RowsPerStrip;i++)
{
switch(BF.Compression)
{
case NO_COMPRESSION:
Seek(fh,BF.StripOffsets[i],OFFSET_BEGINNING);
if(Read(fh,buffer,BF.StripByteCounts[i])!=BF.StripByteCounts[i])
{
DB (KPrintF ("Unable to read strip %ld\n",i));
goto abort;
}
break;
case LZW:
buffer3=AllocPooled(pool,BF.StripByteCounts[i]);
if(!buffer3)
{
DB (KPrintF ("Unable to allocate buffer %ld\n",(long)BF.StripByteCounts[i]));
goto abort;
}
Seek(fh,BF.StripOffsets[i],OFFSET_BEGINNING);
if(Read(fh,buffer3,BF.StripByteCounts[i])!=BF.StripByteCounts[i])
{
DB (KPrintF ("Unable to read strip %ld\n",i));
goto abort;
}
j=UnPackLZW(buffer3,buffer,BF.StripByteCounts[i],cb);
DB (KPrintF ("Uncompressed %ld bytes\n",j));
FreePooled(pool,buffer3,BF.StripByteCounts[i]);
break;
default:
DB (KPrintF ("Unsupported Compression\n"));
goto abort;
}
l=0;
switch(BF.PhotometricInterpretation)
{
case BILEVEL_ZERO_IS_BLACK:
case BILEVEL_ZERO_IS_WHITE:
case COLOR_MAPPED_RGB:
if(BF.BitsPerSample[0]==8)
{
DB (KPrintF ("strip %ld\r",i));
Chunky2Planar(tbm.BytesPerRow*8*BF.RowsPerStrip,buffer,tbm.Planes[0]);
DB (KPrintF ("c2p %ld\n",tbm.BytesPerRow*8*BF.RowsPerStrip));
// WritePixelLine8(&rp,0,k+i*BF.RowsPerStrip,BF.ImageWidth,buffer2,&trp);
if(BF.ImageWidth&0xf) /* image width is not a multiple of 16 */
for(k=0;k<BF.RowsPerStrip&& k+i*BF.RowsPerStrip<BF.ImageLength;k++)
BltBitMap(&tbm,k*BF.ImageWidth,0,bm,0,k+i*BF.RowsPerStrip,BF.ImageWidth,1,0xc0,0xff,NULL);
else
BltBitMap(&tbm,0,0,bm,0,i*BF.RowsPerStrip,BF.ImageWidth,BF.RowsPerStrip,0xc0,0xff,NULL);
}
if(BF.BitsPerSample[0]==1)
for(k=0;k<BF.RowsPerStrip && k+i*BF.RowsPerStrip<BF.ImageLength;k++)
{
DB (KPrintF ("line %ld\r",k+i*BF.RowsPerStrip));
memcpy(bm->Planes[0]+m,buffer+l,(BF.ImageWidth+7)/8);
m+=bm->BytesPerRow;
l+=(BF.ImageWidth+7)/8;
}
break;
case TRUE_COLOR_RGB:
{
UBYTE r,g,b;
int er,eg,eb,erred,ergreen,erblue,red,green,blue;
ErrRed[0]=ErrGreen[0]=ErrBlue[0]=ErrRed[1]=ErrGreen[1]=ErrBlue[1]=0;
if(BF.PlanarConfiguration==CHUNKY)
{
for(k=0;k<BF.RowsPerStrip && k+i*BF.RowsPerStrip<BF.ImageLength;k++)
{
erred=ErrRed[0];
ergreen=ErrGreen[0];
erblue=ErrBlue[0];
DB (KPrintF ("line %ld\r",k+i*BF.RowsPerStrip));
r=buffer[l++];
g=buffer[l++];
b=buffer[l++];
buffer[k*BF.ImageWidth]= ( (((r+erred)/32)<<5) | (((g+ergreen)/32)<<2) | ((b+erblue)/64) );
er=r & 0x1f;
eg=g & 0x1f;
eb=b & 0x3f;
erred=ErrRed[1];
ErrRed[0]=(er*5)>>4;
ErrRed[1]=er>>4;
erred+=(er*7)>>4;
ergreen=ErrGreen[1];
ErrGreen[0]=(eg*5)>>4;
ErrGreen[1]=eg>>4;
ergreen+=(eg*7)>>4;
erblue=ErrBlue[1];
ErrBlue[0]=(eb*5)>>4;
ErrBlue[1]=eb>>4;
erblue+=(eb*7)>>4;
for(j=1;j<BF.ImageWidth;j++)
{
if(BF.Predictor==HORIZONTAL_DIFFERENCING)
{
red =((buffer[l]+r)&0xff)+erred;
if(red>255) red=255;
r+=buffer[l++];
green=((buffer[l]+g)&0xff)+ergreen;
if(green>255) green=255;
g+=buffer[l++];
blue=((buffer[l]+b)&0xff)+erblue;
if(blue>255) blue=255;
b+=buffer[l++];
}
else
{
red =buffer[l]+erred;
if(red>255) red=255;
r=buffer[l++];
green=buffer[l]+ergreen;
if(green>255) green=255;
g=buffer[l++];
blue=buffer[l]+erblue;
if(blue>255) blue=255;
b=buffer[l++];
}
buffer[k*BF.ImageWidth+j]= ( red & 0xe0) | ((green & 0xe0)>>3) | ((blue &0xc0)>>6);
er=red & 0x1f;
eg=green & 0x1f;
eb=blue & 0x3f;
erred=ErrRed[j+1];
ErrRed[j-1]+=(er*3)>>4;
ErrRed[j]+=(er*5)>>4;
ErrRed[j+1]=er>>4;
erred+=(er*7)>>4;
ergreen=ErrGreen[j+1];
ErrGreen[j-1]+=(eg*3)>>4;
ErrGreen[j]+=(eg*5)>>4;
ErrGreen[j+1]=eg>>4;
ergreen+=(eg*7)>>4;
erblue=ErrBlue[j+1];
ErrBlue[j-1]+=(eb*3)>>4;
ErrBlue[j]+=(eb*5)>>4;
ErrBlue[j+1]=eb>>4;
erblue+=(eb*7)>>4;
}
// WritePixelLine8(&rp,0,k+i*BF.RowsPerStrip,(BF.ImageWidth+15)&~7,buffer2,&trp);
}
Chunky2Planar(tbm.BytesPerRow*8*BF.RowsPerStrip,buffer,tbm.Planes[0]);
// if(BF.ImageWidth&0x1f) /* image width is not a multiple of 32 */
for(k=0;k<BF.RowsPerStrip&& k+i*BF.RowsPerStrip<BF.ImageLength;k++)
BltBitMap(&tbm,(k*BF.ImageWidth)%(tbm.BytesPerRow*8),(k*BF.ImageWidth)/(tbm.BytesPerRow*8),bm,0,k+i*BF.RowsPerStrip,BF.ImageWidth,1,0xc0,0xff,NULL);
// else
// BltBitMap(&tbm,0,0,bm,0,i*BF.RowsPerStrip,BF.ImageWidth,BF.RowsPerStrip,0xc0,0xff,NULL);
}
if(BF.PlanarConfiguration==PLANAR) /* This is not implemented yet, since I couldn't find
an image to test it */
for(k=0;k<BF.RowsPerStrip && k+i*BF.RowsPerStrip<BF.ImageLength;k++)
{
DB (KPrintF ("line %ld\r",k+i*BF.RowsPerStrip));
// memcpy(buffer2,buffer+l,BF.ImageWidth+16);
// WritePixelLine8(&rp,0,k+i*BF.RowsPerStrip,BF.ImageWidth,buffer2,&trp);
l+=BF.ImageWidth;
}
}
break;
default:
DB (KPrintF ("Unsupported PhotometricInterpretation\n"));
goto abort;
}
}
setdtattrs (cb, o,
DTA_NominalHoriz, BF.ImageWidth,
DTA_NominalVert, BF.ImageLength,
PDTA_BitMap, bm,
PDTA_ModeID, modeid,
TAG_DONE);
DeletePool(poolchip);
DB (KPrintF ("converted\n"));
return TRUE;
abort:
DeletePool(poolchip);
FreeBitMap (bm);
SetIoErr (ERROR_NO_FREE_STORE);
return FALSE;
}/*************************** convert ************************/